package com.sf.shiva.oms.common.util;

import java.io.ByteArrayOutputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.sf.shiva.oms.common.exception.OmsRuntimeException;


/**
 * 描述:反射工具类
 * 
 * <pre>
 * HISTORY
 * ****************************************************************************
 *  ID   DATE           PERSON            REASON
 *  1    2016-6-13      80002088        Create
 *  2     2016-08-29        866321            增加getFieldValue方法 
 * ****************************************************************************
 */
public class ReflectionUtils {
    
    private static final Logger logger = LoggerFactory.getLogger(ReflectionUtils.class);
    
    private ReflectionUtils(){}
    
    /**
     * 通过类名反射
     * @param className 类名
     * @return
     */
    public static Object newInstance(String className) {
        try {
            return Class.forName(className).newInstance();
        } catch (Exception e) {
            throw new OmsRuntimeException(e);
        }
    }
    /**
     * 通过类反射
     * @param clazz 类
     * @return
     */
    public static <T> T newInstance(Class<T> clazz) {
        try {
            return clazz.newInstance();
        } catch (Exception e) {
            throw new OmsRuntimeException(e);
        }
    }

    /**
     * 类名带参数反射
     * @param className 类名
     * @param parameterTypes 参数类型
     * @param initargs 参数
     * @return
     */
    public static Object newInstance(String className,
            Class<?>[] parameterTypes, Object[] initargs) {
        try {
            return newInstance(Class.forName(className), parameterTypes,
                    initargs);
        } catch (Exception e) {
            throw new OmsRuntimeException(e);
        }
    }

    /**
     * 类带参数反射
     * @param clazz 类
     * @param parameterTypes 参数类型
     * @param initargs 参数
     * @return
     */
    public static <T> T newInstance(Class<T> clazz, Class<?>[] parameterTypes,
            Object[] initargs) {
        try {
            return clazz.getConstructor(parameterTypes).newInstance(initargs);
        } catch (Exception e) {
            throw new OmsRuntimeException(e);
        }
    }

    /**
     * 序列化
     * @param object
     * @return
     */
    public static byte[] serialize(Object object) {
        ObjectOutputStream oos = null;
        ByteArrayOutputStream baos = null;
        byte[] bytes=null;
        try {
            // 序列化
            baos = new ByteArrayOutputStream();
            oos = new ObjectOutputStream(baos);
            oos.writeObject(object);
            bytes = baos.toByteArray();
        } catch (Exception e) {
            logger.error("ReflectionUtils serialize execute error",e);
        }
        return bytes;
    }
    
    /**
     * 根据指定属性的getter获取属性值
     * 
     * @param data
     *            实体类实例
     * @param field
     *            指定的属性
     * @return 属性值
     * @author 866321 于 2016-08-29
     */
    public static <E> Object getFieldValue(E data, String field) {
        Class<?> clazz = data.getClass();
        try {
            String getMethodName = "get".concat(field.substring(0, 1).toUpperCase()).concat(field.substring(1));
            Object value = clazz.getMethod(getMethodName).invoke(data);
            return value;
        } catch (Exception e) {
            throw new OmsRuntimeException(e);
        }
    }
    
    
    /**
     * 获取指定实体类实例的所有属性
     * 
     * @param data
     *            实体类实例
     * @return 所有属性
     * @author 866321 于 2016-08-29
     */
    public static <E> List<Field> getAllField(E data) {
        Class<?> clazz = data.getClass();
        return getAllField(clazz);
    }

    /**
     * 获取指定实体类的所有属性
     * 
     * @param data
     * @return
     * @author la.01367604-2018年6月5日
     */
    public static <T> List<Field> getAllField(Class<T> clazz) {
        List<Field> result = new ArrayList<Field>();
        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {
            result.add(field);
        }
        return result;
    }
    
     
}
